package pr1.cruce;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import pr1.cromosoma.Cromosoma;
import pr1.cromosoma.CromosomaFactory;

public class CruceSimple<E> implements EstrategiaCruce<E>{

	private CromosomaFactory factory;
	
	public CruceSimple(CromosomaFactory factory) {
		this.factory = factory;
	}
	
	@Override
	public void cruce(List<Cromosoma<E>> poblacion, double probCruce, List<Cromosoma<E>> hijos) {
	
		int punto_cruce;
		
		List<Cromosoma<E>> cruzados = new ArrayList<Cromosoma<E>>();
		Cromosoma<E> hijo1 = null;
		Cromosoma<E> hijo2 = null;

        int hijosIndex = 0;
		
		for (Cromosoma<E> cr : poblacion) {
			double prob = Math.random();

			if (prob < probCruce) {
				cruzados.add(cr);
			}
			else {
				hijos.get(hijosIndex).copia(cr);
                hijosIndex++;
			}
		}

		punto_cruce = (int) (Math.random() * hijos.get(0).getGenes().length);

		Iterator<Cromosoma<E>> it = cruzados.iterator();

//        int aux = hijosIndex;

		while (it.hasNext()){
			
			Cromosoma<E> padre1 = it.next();
			if (it.hasNext()) {
				Cromosoma<E> padre2 = it.next();
				
				hijo1 = hijos.get(hijosIndex);
                hijosIndex++;
				hijo2 = hijos.get(hijosIndex);
                hijosIndex++;

                boolean [] gh1 = hijo1.getGenes();
                boolean [] gh2 = hijo2.getGenes();
                boolean [] gp1 = padre1.getGenes();
                boolean [] gp2 = padre2.getGenes();
				
				for (int i = 0; i < punto_cruce; i++){
                    gh1[i] = gp1[i];
                    gh2[i] = gp2[i];
				}
				
				for (int i = punto_cruce; i < padre1.getGenes().length; i++){
					gh1[i] = gp2[i];
                    gh2[i] = gp1[i];
				}
            }
            else {
                hijos.get(hijosIndex).copia(padre1);
                hijosIndex++;
            }
		}
        assert (hijosIndex == hijos.size());
	}

    @Override
    public String toString() {
        return "Simple";
    }
}
